package com.groupbuying.redpacket.service.impl;

import com.groupbuying.redpacket.bo.RedPacketLimitBO;
import com.groupbuying.redpacket.connector.TaskFeign;
import com.groupbuying.redpacket.constants.*;
import com.groupbuying.redpacket.dao.RedPacketTaskDao;
import com.groupbuying.redpacket.domain.RedPacketRuleDO;
import com.groupbuying.redpacket.domain.RedPacketTaskDO;
import com.groupbuying.redpacket.dto.RedPacketTaskDTO;
import com.groupbuying.redpacket.dto.RedPacketTaskVo;
import com.groupbuying.redpacket.service.ActivityThemeService;
import com.groupbuying.redpacket.service.GenerateRedPacketService;
import com.groupbuying.redpacket.service.RedPacketTaskService;
import com.groupbuying.redpacket.service.RuleService;
import com.groupbuying.redpacket.utils.DateUtils;
import com.groupbuying.redpacket.utils.RedisUtils;
import com.groupbuying.redpacket.utils.apiresult.ApiResult;
import com.groupbuying.redpacket.utils.apiresult.ApiResultCode;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Service
public class RedPacketTaskServiceImpl implements RedPacketTaskService {
    private static final Logger logger = LoggerFactory.getLogger(RedPacketListServiceImpl.class);

    @Autowired
    private RedPacketTaskDao redPacketTaskDao;

    @Autowired
    private RuleService ruleService;

    @Autowired
    private GenerateRedPacketService generateRedPackageService;

    @Autowired
    private ActivityThemeService activityThemeService;

    @Autowired
    private TaskFeign taskFeign;

    @Autowired
    private RedisUtils redisUtils;


    @Transactional(rollbackFor = Exception.class)
    @Override
    public ApiResult addTaskAndRule(RedPacketTaskDO redPacketTask, List<RedPacketRuleDO> redPacketRuleDOS) {
        //判断标识
        boolean flag = true;
        //判断所属分类不可为空
        if (redPacketTask.getAppFlag() == null) {
            logger.error("错误提示:所属分类不可为空");
            return ApiResult.failure("所属分类不可为空");
        }

        //判断主题名称
        if (StringUtils.isEmpty(redPacketTask.getTheme()) && redPacketTask.getTheme().length() > 12) {
            logger.error("错误提示:请输入正确格式的主题名");
            return ApiResult.failure("请输入正确格式的主题名");
        }


        RedPacketTaskDO redPacketTaskDO = redPacketTaskDao.getAppFlag(redPacketTask.getAppFlag(), redPacketTask.getRound());
        //判断同一所属分类下轮次不可重复
        if (redPacketTaskDO != null) {
            logger.error("错误提示:轮次冲突");
            return ApiResult.failure("轮次冲突");
        }

        // 这里判断 定时任务和手动开启任务的时间逻辑
        if (redPacketTask.getStartType() == 1) {  //1代表定时
            if (redPacketTask.getStartTime() == null && redPacketTask.getEndTime() == null) {//开始结束时间
                logger.error("错误提示:开始和结束时间不可为空");
                return ApiResult.failure("开始和结束时间不可为空");
            }
            List<RedPacketTaskDO> list = redPacketTaskDao.contrastTime(null);
            if (list.size() != 0 && list != null) {
                for (int i = 0; i < list.size(); i++) {
                    if (redPacketTask.getStartTime().getTime() <= list.get(i).getEndTime().getTime() && redPacketTask.getEndTime().getTime() >= list.get(i).getStartTime().getTime()) {
                        flag = false;
                        break;
                    } else {
                        continue;
                    }
                }
                if (!flag) {
                    logger.error("错误提示:该时间段已有任务");
                    return ApiResult.failure("该时间段已有任务");
                }
            }
            //计算持续时间（前端是否能传）
            int keepTime = (int) (redPacketTask.getEndTime().getTime() - redPacketTask.getStartTime().getTime()) / 1000;
            redPacketTask.setKeepTime(keepTime);
        } else { //代表手动
            // 手动操作 持续时间不能为空
            if (redPacketTask.getKeepTime() == null) {
                logger.error("错误提示:持续时间不可为空");
                return ApiResult.failure("持续时间不可为空");
            }

        }

        //判断总金额验证
        if (redPacketTask.getTotalAmount() == null) {
            logger.error("错误提示:总金额不可为空");
            return ApiResult.failure("总金额不可为空");

        }
        //判断红包类型取值范围
        BigDecimal calTotal = new BigDecimal("0");
        for (RedPacketRuleDO redPacketRuleDO : redPacketRuleDOS) {
            calTotal = calTotal.add(redPacketRuleDO.getTotalAmount());
            BigDecimal avgResult = redPacketRuleDO.getTotalAmount().divide(new BigDecimal(redPacketRuleDO.getTotalCount()), 2, RoundingMode.UP);

            int compareMax = avgResult.compareTo(redPacketRuleDO.getMaxAmount());
            int compareMin = avgResult.compareTo(redPacketRuleDO.getMinAmount());
            if (compareMin == -1 || compareMax == 1) {
                logger.error("错误提示:红包类型中金额的取值范围超限");
                return ApiResult.failure("红包金额范围区间不合理");
            }
        }
        //判断各个类型红包综合是否和总金额一致
        if (redPacketTask.getTotalAmount().compareTo(calTotal) == -1) {
            logger.error("错误提示:总金额和红包类型总额不匹配");
            return ApiResult.failure("总金额和红包类型总额不匹配");
        }
        //创建时间
        redPacketTask.setCreateTime(new Date());

        //状态默认未开始
        redPacketTask.setExecuteState(0);
        try {
            // 保存任务
            redPacketTaskDao.save(redPacketTask);
            //保存红包类型规则
            ruleService.insertBatch(redPacketTask, redPacketRuleDOS);
            //根据规则生成红包
            generateRedPackageService.GenerateRedPackage(redPacketTask.getId().toString());
            //TODO 处理定时任务的开启逻辑
            if (redPacketTask.getStartType() == 1) {
                taskFeign.setRule(DateUtils.format(new Date(redPacketTask.getStartTime().getTime() - 6000L), DateUtils.TIMING), redPacketTask.getId().toString());
            }


        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ApiResult.failure("错误提示:添加失败");
        }
        return ApiResult.success();
    }


    /**
     * 编辑红包任务
     *
     * @param redPacketTask    任务对象
     * @param redPacketRuleDOS
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ApiResult updateTaskAndRule(RedPacketTaskDO redPacketTask, List<RedPacketRuleDO> redPacketRuleDOS) {
        //判断标识
        boolean flag = true;
        //判断所属分类不可为空
        if (redPacketTask.getAppFlag() == null) {
            logger.error("错误提示:所属分类不可为空");
            return ApiResult.failure("所属分类不可为空");
        }

        //判断主题名称
        if (StringUtils.isEmpty(redPacketTask.getTheme()) && redPacketTask.getTheme().length() > 12) {
            logger.error("错误提示:请输入正确格式的主题名");
            return ApiResult.failure("请输入正确格式的主题名");
        }

        RedPacketTaskDO redPacketTaskDO = redPacketTaskDao.getAppFlag(redPacketTask.getAppFlag(), redPacketTask.getRound());
        //判断同一所属分类下轮次不可重复
        if (redPacketTaskDO != null && redPacketTaskDO.getRound() != redPacketTask.getRound()) {
            logger.error("错误提示:轮次冲突");
            return ApiResult.failure("轮次冲突");
        }

        //TODO 这里判断 定时任务和手动开启任务的时间逻辑
        if (redPacketTask.getStartType() == 1) {  //1代表定时
            if (redPacketTask.getStartTime() == null && redPacketTask.getEndTime() == null) {//开始结束时间
                logger.error("错误提示:开始或结束时间不可为空");
                return ApiResult.failure("开始或结束时间不可为空");
            }
            List<RedPacketTaskDO> list = redPacketTaskDao.contrastTime(redPacketTask.getId());
            if (list.size() != 0 && list != null) {
                for (int i = 0; i < list.size(); i++) {
                    if (redPacketTask.getStartTime().getTime() <= list.get(i).getEndTime().getTime() && redPacketTask.getEndTime().getTime() >= list.get(i).getStartTime().getTime()) {
                        flag = false;
                        break;
                    } else {
                        continue;
                    }
                }
                if (!flag) {
                    logger.error("错误提示:该时间段已有任务");
                    return ApiResult.failure("该时间段已有任务");
                }
            }
            //TODO 计算持续时间（前端是否能传）
        } else { //代表手动
            // 手动操作 持续时间不能为空
            if (redPacketTask.getKeepTime() == null) {
                logger.error("错误提示:持续时间不可为空");
                return ApiResult.failure("持续时间不可为空");
            }

        }

        //判断总金额验证
        if (redPacketTask.getTotalAmount() == null) {
            logger.error("错误提示:总金额不可为空");
            return ApiResult.failure("总金额不可为空");

        }
        //判断红包类型取值范围
        BigDecimal calTotal = new BigDecimal("0");
        for (RedPacketRuleDO redPacketRuleDO : redPacketRuleDOS) {
            calTotal = calTotal.add(redPacketRuleDO.getTotalAmount());
            BigDecimal avgResult = redPacketRuleDO.getTotalAmount().divide(new BigDecimal(redPacketRuleDO.getTotalCount()), 2, RoundingMode.UP);

            int compareMax = avgResult.compareTo(redPacketRuleDO.getMaxAmount());
            int compareMin = avgResult.compareTo(redPacketRuleDO.getMinAmount());
            if (compareMin == -1 || compareMax == 1) {
                logger.error("错误提示:红包类型中金额的取值范围超限");
                return ApiResult.failure("红包金额范围区间不合理");
            }
        }
        //判断各个类型红包综合是否和总金额一致
        if (redPacketTask.getTotalAmount().compareTo(calTotal) == -1) {
            logger.error("错误提示:总金额和红包类型总额不匹配");
            return ApiResult.failure("总金额和红包类型总额不匹配");
        }
        //TODO 1 判断单人红包限制数量（数量判空）
        //TODO 2 判断单人红包限制金额 （金额判空）
        //更新时间
        redPacketTask.setUpdateTime(new Date());
        String id = redPacketTask.getId().toString();
        try {
            //TODO 删除类型规则
            ruleService.deleteByTaskId(id);
            //TODO 保存任务
            redPacketTaskDao.update(redPacketTask);
            //保存之后才能拿到taskId
            //TODO 保存红包类型规则
            ruleService.insertBatch(redPacketTask, redPacketRuleDOS);
            //TODO 根据规则生成红包
            generateRedPackageService.GenerateRedPackage(redPacketTask.getId().toString());

            if (redPacketTask.getStartType() == 1) {
                taskFeign.setRule(DateUtils.format(new Date(redPacketTask.getStartTime().getTime() - 6000L), DateUtils.TIMING), redPacketTask.getId().toString());
            }

        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ApiResult.failure("错误提示:修改失败");
        }
        return ApiResult.success();
    }

    @Override
    public ApiResult nowTaskStateService() {

        //返回参数
        Map<String, Object> retMap = new HashMap<>();

        //获取redis 信息
        boolean running = redisUtils.isHasKey(RedisConstans.RED_PACKAGE_CONTROL);
        boolean settle = redisUtils.isHasKey(RedisConstans.RED_PACKAGE_CONTROL_SETTLE);
        //查看定时锁是否存在
        boolean timerKey = redisUtils.isHasKey(RedisConstans.RED_PACKAGE_HAS_TIMER);

        //运行状态
        if (running) {
            //获取限制信息
            logger.info("第一次查询运行状态,提示信息：当前大屏状态为正在执行任务状态");
            getRedPacketLimitInfo(retMap, LargeScreenConstants.LARGE_SCREEN_STATE_RUNNING);
            return ApiResult.success(ApiResultCode.SUCCESS, retMap);
        }

        //结算状态
        if (!running && settle) {

            //有任务直接退出结算时间
            if (timerKey) {
                logger.info("提示信息：当前大屏状态为倒计时状态");
                retMap.put("state", LargeScreenConstants.LARGE_SCREEN_STATE_TIME);
                retMap.put("limit", "");
                return ApiResult.success(ApiResultCode.SUCCESS, retMap);
            }

            logger.info("提示信息：当前大屏状态为结算状态");
            getRedPacketLimitInfo(retMap, LargeScreenConstants.LARGE_SCREEN_STATE_SETTLE);
            return ApiResult.success(ApiResultCode.SUCCESS, retMap);
        }

        //倒计时状态
        if (timerKey) {
            logger.info("提示信息：当前大屏状态为倒计时状态");
            retMap.put("state", LargeScreenConstants.LARGE_SCREEN_STATE_TIME);
            retMap.put("limit", "");
            return ApiResult.success(ApiResultCode.SUCCESS, retMap);
        }

        //大屏首页
        logger.info("提示信息：当前大屏状态为首页展示状态");
        retMap.put("state", LargeScreenConstants.LARGE_SCREEN_STATE_NON_TASK);
        retMap.put("limit", "");
        return ApiResult.success(ApiResultCode.SUCCESS, retMap);
    }

    /**
     * 获取红包限制信息
     *
     * @param retMap           返回map
     * @param largeScreenState 当前大屏状态
     */
    private void getRedPacketLimitInfo(Map<String, Object> retMap, String largeScreenState) {
        RedPacketLimitBO redPacketLimitBO = (RedPacketLimitBO) redisUtils.getValue(RedisConstans.RED_PACKAGE_CONTROL_SETTLE);

        if (redPacketLimitBO == null) {
            logger.error("错误提示:redis红包限制信息查询位空");
            ApiResult.success(ApiResultCode.RESULT_NULL);
        }

        retMap.put("state", largeScreenState);
        retMap.put("limit", redPacketLimitBO);
    }

    @Override
    public List<RedPacketTaskVo> listTask(Map<String, Object> map) {

        List<RedPacketTaskVo> redPacketTaskVos = redPacketTaskDao.listTask(map);
        for (int i = 0; i < redPacketTaskVos.size(); i++) {
            //活动状态
            if (redPacketTaskVos.get(i).getExecuteState() == 0) {
                redPacketTaskVos.get(i).setExecuteStates("未开始");
            } else if (redPacketTaskVos.get(i).getExecuteState() == 1) {
                redPacketTaskVos.get(i).setExecuteStates("进行中");
            } else {
                redPacketTaskVos.get(i).setExecuteStates("已结束");
            }
            //启动方式
            if (redPacketTaskVos.get(i).getStartType() == 1) {
                redPacketTaskVos.get(i).setStartTypes("定时启动");
            } else {
                redPacketTaskVos.get(i).setStartTypes("手动启动");
            }
            redPacketTaskVos.get(i).setThemeName(activityThemeService.getThemeName(Long.valueOf(redPacketTaskVos.get(i).getAppFlag())));
        }
        for (int i = 0; i < redPacketTaskVos.size(); i++) {
            redPacketTaskVos.get(i).setRedPacketRuleDOS(ruleService.rulebyTaskId(redPacketTaskVos.get(i).getId().toString()));
        }
        return redPacketTaskVos;
    }

    @Override
    public int getCount() {
        return redPacketTaskDao.getCount();
    }

    @Override
    public ApiResult getTask(Long id) {
        RedPacketTaskDTO redPacketTaskDTO = redPacketTaskDao.getTask(id);
        try {
            redPacketTaskDTO.setRedPacketRuleDOS(ruleService.rulebyTaskId(redPacketTaskDTO.getId().toString()));
        } catch (Exception e) {
            return ApiResult.failure("没有该任务");
        }
        return ApiResult.success(redPacketTaskDTO);
    }


    @Override
    public RedPacketTaskDO get(Long id) {
        return redPacketTaskDao.get(id);
    }

    @Override
    public List<RedPacketTaskDO> list(Map<String, Object> map) {
        return redPacketTaskDao.list(map);
    }

    @Override
    public int count(Map<String, Object> map) {
        return redPacketTaskDao.count(map);
    }

    @Override
    public int save(RedPacketTaskDO redPacketTask) {
        return redPacketTaskDao.save(redPacketTask);
    }

    @Override
    public int update(RedPacketTaskDO redPacketTask) {
        return redPacketTaskDao.update(redPacketTask);
    }

    @Override
    public int remove(Long id) {
        return redPacketTaskDao.remove(id);
    }

    @Override
    public int batchRemove(Long[] ids) {
        return redPacketTaskDao.batchRemove(ids);
    }

}
